<template>
  <a-spin tip="加载中..." :spinning="spinning">
    <div class="photo-container">
      <div class="blank"></div>
      <!-- 背景区 -->
      <div class="background-info">
        <div class="title-txt">
          <p style="font-size: 20px;font-weight: bold;">时光相簿</p>
          <p style="font-weight: bold;font-size: 14px;">
            这方简洁天地，是时光琥珀的陈列馆。多格式照片在此栖居，可随心编织成册，分类标注似缀上时光书签，让美好回忆永不褪色，随时温柔绽放。</p>
        </div>

        <svg v-if="showAddBtn" @click="showAddPhotoModel" t="1753346421804" class="icon addBtn" viewBox="0 0 1024 1024"
             version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="48741" width="200" height="200">
          <path
              d="M576.512 560.0768m-354.9696 0a354.9696 354.9696 0 1 0 709.9392 0 354.9696 354.9696 0 1 0-709.9392 0Z"
              fill="#56E5BE" p-id="48742"></path>
          <path
              d="M612.1984 595.712m-319.2832 0a319.2832 319.2832 0 1 0 638.5664 0 319.2832 319.2832 0 1 0-638.5664 0Z"
              fill="#50DDB8" p-id="48743"></path>
          <path
              d="M648.6528 621.7216m-277.6064 0a277.6064 277.6064 0 1 0 555.2128 0 277.6064 277.6064 0 1 0-555.2128 0Z"
              fill="#42D3AD" p-id="48744"></path>
          <path
              d="M511.8976 920.0128c-227.3792 0-412.3648-184.9856-412.3648-412.3648s184.9856-412.3648 412.3648-412.3648 412.3648 184.9856 412.3648 412.3648-184.9856 412.3648-412.3648 412.3648z m0-763.2384c-193.4848 0-350.9248 157.44-350.9248 350.9248s157.44 350.9248 350.9248 350.9248 350.9248-157.44 350.9248-350.9248-157.44-350.9248-350.9248-350.9248z"
              fill="#2E3138" p-id="48745"></path>
          <path
              d="M651.7248 466.6368h-108.0832V358.5536c0-16.9472-13.7728-30.72-30.72-30.72s-30.72 13.7728-30.72 30.72v108.0832H374.1184c-16.9472 0-30.72 13.7728-30.72 30.72s13.7728 30.72 30.72 30.72h108.0832v108.0832c0 16.9472 13.7728 30.72 30.72 30.72s30.72-13.7728 30.72-30.72v-108.0832h108.0832c16.9472 0 30.72-13.7728 30.72-30.72s-13.7728-30.72-30.72-30.72z"
              fill="#2E3138" p-id="48746"></path>
        </svg>
      </div>
      <!-- 标签区 -->
      <div class="tag-container">
                <span class="tag" v-for="(item, index) in tagList" :key="index" @click="changeTag(item)">
                    {{ item.tagName }}&nbsp;{{ item.count }}
                </span>
      </div>
      <!-- 标题区 -->
      <div class="tag-title">
        {{ selectedTag.tagName }}
      </div>
      <!-- 图片区 -->
      <div class="img-container">
        <div class="card-item" v-for="(item, index) in imgList" :key="index">
          <div class="img-div">
            <img :src="item.url" :alt="item.photoName"
                 @click="openFullscreenPreview(item.url, item.photoName)">
          </div>
          <div class="img-name">{{ item.photoName }}</div>
          <div>Date: {{ item.takeTime }}</div>
        </div>
      </div>
    </div>
  </a-spin>
  <a-modal v-model:open="addPhotoModel" title="添加相册" :maskClosable="false">
    <template #footer>
      <a-button key="back" @click="handleCancel1">取消</a-button>
      <a-button key="submit" type="primary" :loading="loading" @click="savePhoto">确定</a-button>
    </template>
    <a-input v-model:value="addPhotoForm.photoName" placeholder="相册名称"/>
    <a-modal :open="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancel2">
      <img style="width: 100%" :src="previewImage"/>
    </a-modal>
    <a-select v-model:value="addPhotoForm.tagList" mode="tags" style="width: 100%; margin: 10px 0;" placeholder="标签"
              :options="tagOptions" @change="selectTag"></a-select>
    <a-date-picker v-model:value="addPhotoForm.takeTime" :locale="locale"/>
    <!-- 图片上传区域 -->
    <a-upload v-model:file-list="fileList" list-type="picture-card" :customRequest="uploadImages"
              style="margin-top: 10px;"
              @preview="handlePreview">
      <div v-if="fileList.length < 1">
        <PlusOutlined/>
      </div>
    </a-upload>
  </a-modal>

  <!-- 全屏预览组件 -->
  <div v-if="fullscreenPreview" class="fullscreen-preview" @click="closeFullscreenPreview">
    <div class="preview-content" @click.stop>
      <button class="preview-close" @click="closeFullscreenPreview">×</button>
      <div class="preview-img-container">
        <img :src="currentPreviewImg" :alt="currentPreviewName"/>
      </div>
      <div class="preview-title">{{ currentPreviewName }}</div>
    </div>
  </div>
</template>

<script setup lang="js">
import {upload2} from '@/api/file';
import {addPhoto, findListByTagId} from "@/api/photo";
import {findList} from "@/api/photoTag";
import {PlusOutlined} from "@ant-design/icons-vue";
import {message} from "ant-design-vue";
import locale from 'ant-design-vue/es/date-picker/locale/zh_CN';
import dayjs from "dayjs";
import 'dayjs/locale/zh-cn';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import {onMounted, reactive, ref} from "vue";

dayjs.extend(localizedFormat);
dayjs.locale('zh-cn');

const showAddBtn = ref(false);
const spinning = ref(false);
const loading = ref(false);
const previewVisible = ref(false);
const previewImage = ref('');
const previewTitle = ref('');
// 模块ID
const moduleId = '6';
// 限制最多上传1张图
const maxImages = 1;
// 单张图片最大20MB
const maxSize = 20 * 1024 * 1024;
// 允许的图片类型
const allowTypes = [
  'image/jpeg',   // JPG/JPEG
  'image/png',    // PNG
  'image/webp',   // WebP
  'image/gif',    // GIF（支持动态图）
  'image/bmp',    // BMP
  'image/tiff',   // TIFF
  'image/svg+xml' // SVG（矢量图）
];
// 图片类型友好名称映射（用于错误提示）
const allowedTypeNames = {
  'image/jpeg': 'JPG/JPEG',
  'image/png': 'PNG',
  'image/webp': 'WebP',
  'image/gif': 'GIF',
  'image/bmp': 'BMP',
  'image/tiff': 'TIFF',
  'image/svg+xml': 'SVG'
};
// 全屏预览相关
const fullscreenPreview = ref(false); // 是否显示全屏预览
const currentPreviewImg = ref('');   // 当前预览的图片地址
const currentPreviewName = ref('');  // 当前预览的图片名称
// 文件列表
const fileList = ref([]);
/* 标签列表 */
const tagList = reactive([]);
/* 照片列表 */
const imgList = reactive([]);
// 当前选中的标签
const selectedTag = reactive({
  id: null,
  tagName: null,
});
// 添加照片模态框显示
const addPhotoModel = ref(false);
// 添加相册模态框显示
const addPhotoForm = reactive({
  tagId: '',
  newTagName: '',
  url: '',
  takeTime: '',
  photoName: '',
  tagList: [],
})
// 标签列表选项
const tagOptions = ref([]);
// 时间选择器格式
const dateFormat = 'YYYY-MM-DD';
// 缩放控制
const scale = ref(1); // 初始缩放比例
const minScale = ref(0.5); // 最小缩放比例
const maxScale = ref(3); // 最大缩放比例

// 放大图片
const zoomIn = () => {
  if (scale.value < maxScale.value) {
    scale.value += 0.1;
  }
};

// 缩小图片
const zoomOut = () => {
  if (scale.value > minScale.value) {
    scale.value -= 0.1;
  }
};

// 重置缩放
const resetZoom = () => {
  scale.value = 1;
};
/* 切换标签 */
const changeTag = (tag) => {
  if (tag.id != selectedTag.id) {
    findPhotoList(tag.id);
  }
  selectedTag.id = tag.id;
  selectedTag.tagName = tag.tagName;
}
/* 根据标签id查询照片列表 */
const findPhotoList = async (tagId) => {
  await findListByTagId({tagId}).then(res => {
    if (res.code === 200) {
      imgList.splice(0)
      Object.assign(imgList, res.data);
    }
  }).catch(err => {
    console.log(err)
  })
}
// 预览图片
const handlePreview = async file => {
  if (!file.url && !file.preview) {
    file.preview = await getBase64(file.originFileObj);
  }
  previewImage.value = file.url || file.preview;
  previewVisible.value = true;
  previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
};
const findDataList = async () => {
  spinning.value = true;
  await findList().then(res => {
    if (res.code === 200) {
      Object.assign(tagList, res.data);
      tagOptions.value = tagList.map(item => {
        return {
          value: item.id,
          label: item.tagName
        }
      });
      if (tagList.length > 0) {
        Object.assign(selectedTag, tagList[0]);
        findPhotoList(selectedTag.id)
      }
      spinning.value = false;
    }
  }).catch(err => {
    console.log(err)
  })
}
// 展示添加图片弹框
const showAddPhotoModel = () => {
  addPhotoForm.takeTime = dayjs(dayjs().format(dateFormat), dateFormat);
  addPhotoModel.value = true;
}
const resetAddPhotoForm = () => {
  addPhotoForm.newTagName = '';
  addPhotoForm.photoName = '';
  addPhotoForm.tagId = '';
  addPhotoForm.url = '';
  addPhotoForm.tagList = [];
  fileList.value = [];
}
// 上传图片
const uploadImages = async ({file}) => {
  if (fileList.value.length > maxImages) {
    message.warn(`最多只能上传${maxImages}张图片`);
    return;
  }
  // 校验图片大小
  if (file.size > maxSize) {
    const sizeInMB = (maxSize / (1024 * 1024)).toFixed(1);
    message.warn(`图片大小不能超过${sizeInMB}MB`);
    return;
  }
  // 校验图片类型
  if (!allowTypes.includes(file.type)) {
    const allowedTypesText = allowTypes.map(type => allowedTypeNames[type] || type).join('、');
    message.warn(`请上传${allowedTypesText}格式的图片`);
    return; // 阻止上传
  }
  // 上传文件
  const formData = new FormData();
  formData.append('file', file);
  formData.append('moduleId', moduleId);
  upload2(formData).then(res => {
    const fileInfo = res.data.data;
    if (res.data.code !== 200 || !fileInfo) {
      message.success("上传失败");
    } else {
      message.success("上传成功");
      file.url = fileInfo.fileAddress;
      file.id = fileInfo.id;
      let newFileList = [];
      for (let i = 0; i < fileList.value.length; i++) {
        let one = fileList.value[i];
        if (!one.originFileObj) {
          newFileList.push(one)
        }
      }
      newFileList.push(file);
      fileList.value = [...newFileList];
      addPhotoForm.url = fileInfo.fileAddress;
    }
  }).catch(err => {
    console.log(err);
  });
};
// 确定保存
const savePhoto = () => {
  if (!addPhotoForm.photoName) {
    message.error("相册名称不能为空");
    return;
  }
  if (!fileList.value.length > 0) {
    message.error("请上传照片");
    return;
  }
  if (!addPhotoForm.tagId && !addPhotoForm.newTagName) {
    message.error("请选择或输入标签");
    return;
  }
  loading.value = true;
  addPhoto(addPhotoForm).then(res => {
    if (res.code == 200 && res.data) {
      message.success("添加成功");
      addPhotoModel.value = false;
      loading.value = false;
      findDataList();
      resetAddPhotoForm();
    }
  }).catch(err => {
    console.log(err);
  });
};
// 取消
const handleCancel1 = () => {
  addPhotoModel.value = false;
};
// 取消预览
const handleCancel2 = () => {
  previewVisible.value = false;
  previewTitle.value = '';
};
// 选择标签
const selectTag = (value) => {
  let selectedTag = '';
  if (addPhotoForm.tagList.length >= 1) {
    selectedTag = addPhotoForm.tagList[addPhotoForm.tagList.length - 1]
    addPhotoForm.tagList = addPhotoForm.tagList[addPhotoForm.tagList.length - 1]
  }

  let isExist = false;
  tagList.forEach(item => {
    if (item.id === selectedTag) {
      isExist = true;
    }
  })
  if (isExist) {
    addPhotoForm.tagId = selectedTag;
  } else {
    addPhotoForm.newTagName = selectedTag;
  }
};

// 打开全屏预览
const openFullscreenPreview = (url, name) => {
  currentPreviewImg.value = url;
  currentPreviewName.value = name;
  fullscreenPreview.value = true;
  // 禁止页面滚动
  document.body.style.overflow = 'hidden';
};

// 关闭全屏预览
const closeFullscreenPreview = () => {
  fullscreenPreview.value = false;
  currentPreviewImg.value = '';
  currentPreviewName.value = '';
  // 恢复页面滚动
  document.body.style.overflow = '';
};

onMounted(async () => {
  await findDataList();

  if (localStorage.getItem("token")) {
    showAddBtn.value = true;
  } else {
    showAddBtn.value = false;
  }
})
</script>

<style scoped lang="less">
.photo-container {
  max-width: var(--screen-max-width);
  margin: 0 auto;
  margin-bottom: 20px;

  .blank {
    height: 80px;
  }

  .background-info {
    height: 150px;
    width: 95%;
    background-image: url('@/assets/img/cute-cups-couple.jpg');
    background-position: center;
    background-size: cover;
    border-radius: 15px;
    margin: 0 auto;
    animation: background-img-move 5s linear infinite alternate;
    color: #fff;
    padding: 28px;
    position: relative;

    &:hover {
      animation-play-state: paused;
    }

    .title-txt {
      width: 80%;
      position: absolute;
      top: 50%;
      left: 50%;
      margin: auto;
      /* 修正自身中心点偏移 */
      transform: translate(-50%, -50%);
      /* 清除默认边距 */
      margin: 0;
    }

    .addBtn {
      font-size: 40px;
      position: absolute;
      top: 0;
      right: 2px;
      // bottom: 0;
      margin: auto;
      cursor: pointer;
    }
  }

  .tag-container {
    display: flex;
    margin: 35px 0 30px 30px;

    .tag {
      border-radius: 10px;
      padding: 10px;
      background-color: skyblue;
      color: #fff;
      font-weight: bold;
      font-size: 20px;
      margin-right: 10px;
      cursor: pointer;

      &:hover {
        background-color: #ff4a31;
      }
    }

    & > .tag:last-child {
      margin-right: 0;
    }
  }

  .tag-title {
    font-size: 35px;
    width: 100%;
    text-align: center;
    margin-bottom: 20px;
    font-weight: bold;
  }

  .img-container {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 25px;
    width: 90%;
    margin: 0 auto;

    .card-item {
      cursor: pointer;
      display: flex;
      flex-direction: column;
      padding: 10px;
      border: 1px solid rgb(241, 232, 232);
      box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
      border-radius: 10px;

      .img-div {
        width: 100%;
        overflow: hidden;
        object-fit: cover;

        img {
          // height: 350px;
          border-radius: 10px;
          object-fit: cover;
          transition: all 0.6s ease-in-out;
          width: 100%;

          &:hover {
            transform: scale(1.3);
            border-radius: 10px;
          }
        }
      }

      div:nth-child(2) {
        font-weight: bold;
        margin: 5px 0;
        font-size: 18px;
      }

      div:last-child {
        font-size: 14px;
        color: var(--text-color3);
      }
    }
  }
}

/* 全屏预览样式 */
.fullscreen-preview {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.9);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  opacity: 0;
  animation: fadeIn 0.3s ease-in-out forwards;
}

.preview-content {
  width: 100%;
  max-width: 90%;
  max-height: 90vh;
  position: relative;
}

.preview-close {
  position: absolute;
  top: -40px;
  right: 0;
  background: transparent;
  border: none;
  color: white;
  font-size: 30px;
  cursor: pointer;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover {
    color: #ff4d4f;
  }
}

.preview-img-container {
  display: flex;
  align-items: center;
  justify-content: center;
  max-height: 80vh;
  overflow: hidden;

  img {
    max-width: 100%;
    max-height: 80vh;
    object-fit: contain;
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
    transition: transform 0.3s ease;

    &:hover {
      transform: scale(1.02);
    }
  }
}

.preview-title {
  // color: white;
  text-align: center;
  margin-top: 20px;
  font-size: 16px;
  padding: 10px;
  background-color: rgba(255, 255, 255, 0.1);
  border-radius: 4px;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes background-img-move {
  0% {
    background-position: 0% 30%;
  }

  100% {
    background-position: 100% 100%;
  }
}
</style>